/**
 ******************************************************************************
 * @file    STM32F0xx_IAP/src/main.c
 * @author  MCD Application Team
 * @version V1.0.0
 * @date    29-May-2012
 * @brief   Main program body
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
 *
 * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *        http://www.st.com/software_license_agreement_liberty_v2
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "Global_types.h"
#include "SerialInterface.h"
#include "main.h"
#include "Sensor.h"
#include "Condition.h"
#include "Task.h"
#include "Block.h"
#include "Scheduler.h"
#include "CommandHandler.h"
#include "TimeManager.h"
#include "stm32f0xx_usart.h"
#include "Global_types.h"
#include "StringManager.h"
#include "Scheduler.h"
#include "ConditionBlock.h"
#include "DelayBlock.h"
//#include "GPIO.hpp"

CommandType cmd;
/** @addtogroup STM32F0xx_IAP
 * @{
 */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern pFunction Jump_To_Application;
extern uint32_t JumpAddress;
/* Private function prototypes -----------------------------------------------*/
static void IAP_Init(void);

volatile unsigned int a = 500;
volatile uint32_t b = 2000;
volatile uint32_t c = 3000;
volatile uint32_t d = 4000;
volatile uint32_t x = 0;
uint8_t byte;
/* Private functions ---------------------------------------------------------*/
//inline void SysTick_CallBack(void)
//{
//  TimeManager::UpdateSystemTime();
//}
//inline void USART_ByteReceived(void)
//{
//uint8_t byte= USART_ReceiveData(USART1);
//if(byte==CommandHandler::getMessageEndChar())
//{
//  Scheduler::sendEvent(COMMAND_RECEIVED);
//  return;
//}
//}
/**
 * @brief  Main program.
 * @param  None
 * @retval None
 */
ErrorCode callback(void *args)
  {

    const char* str =
      {
      "Hello!\r\n"
      };
    Int2Str((uint8_t*) str, ((int32_t) args));
    return NO_ERR;
  }

int main(void)
  {
    /*!< At this stage the microcontroller clock setting is already configured,
     this is done through SystemInit() function which is called from startup
     file (startup_stm32f0xx.s) before to branch to application main.
     To reconfigure the default setting of SystemInit() function, refer to
     system_stm32f0xx.c file
     */

    /* Initialize Key Button mounted on STM320518-EVAL board */
    STM_EVAL_PBInit(BUTTON_KEY, BUTTON_MODE_GPIO);
    IAP_Init();
    //Log(SENSOR, NO_ERR, (char*) "test");
    // Log(SENSOR, NO_ERR, (char*) "created2!");
//      Log(SENSOR, NO_ERR, (char*) "created3!");
// CommandHandler::Init();
// CommandHandler::addMessagebyte('l');
// CommandHandler::addMessagebyte('s');
//cmd =CommandHandler::retrieveCommandFromString();
    RCC_ClocksTypeDef RCC_Clocks;

    /* Configure LED3 and LED4 on STM32F0-Discovery */
    STM_EVAL_LEDInit (LED1);
    STM_EVAL_LEDInit (LED2);
    STM_EVAL_LEDInit (LED3);
    STM_EVAL_LEDInit (LED4);
    Led_TypeDef led1 = LED1;
    Led_TypeDef led2 = LED2;
    Led_TypeDef led3 = LED3;
    Led_TypeDef led4 = LED4;

    STM_EVAL_LEDOn((void*) &led1);
    STM_EVAL_LEDOff((void*) &led1);

    STM_EVAL_LEDOn((void*) &led3);
    STM_EVAL_LEDOff((void*) &led3);
    STM_EVAL_LEDOn((void*) &led4);
    STM_EVAL_LEDOff((void*) &led4);
    TimeManager::Init();

    //char buf[6]="Hello";
    volatile uint32_t *timeptr;
    //TimeManager::GetSystemTime();
    timeptr = TimeManager::GetSystemTime();
    //Condition<uint32_t > *cond= new Condition<uint32_t > (3,&a, PLUS, &b,PLUS, &x, EQUAL, &c);
//	Condition<uint32_t> *cond = new Condition<uint32_t>(1, timeptr, MORE_EQUAL, &x);

//    Condition<volatile unsigned int> *cond1 = new Condition<volatile unsigned int>(timeptr, MOD, &a, EQUAL, &x);
//    Condition<volatile unsigned int> *cond2 = new Condition<volatile unsigned int>(timeptr, MOD, &a, EQUAL, &x);
//    Condition<volatile unsigned int> *cond3 = new Condition<volatile unsigned int>(timeptr, MOD, &b, EQUAL, &x);
//    Condition<volatile unsigned int> *cond4 = new Condition<volatile unsigned int>(timeptr, MOD, &b, EQUAL, &x);
//                Condition<volatile unsigned int> *cond2 = new Condition<volatile unsigned int>(timeptr, MOD, &b, EQUAL, &x);
//                    Condition<volatile unsigned int> *cond2 = new Condition<volatile unsigned int>(timeptr, MOD, &b, EQUAL, &x);
//    Condition<volatile unsigned int> *cond3 = new Condition<volatile unsigned int>(timeptr, MOD, &c, EQUAL, &x);
//    Condition<volatile unsigned int> *cond4 = new Condition<volatile unsigned int>(timeptr, MOD, &d, EQUAL, &x);

    Task * task1 = new Task((char*) "LED1_OFF", STM_EVAL_LEDOff, (void*) &led1, DISABLED);
    Task * task2 = new Task((char*) "LED1_ON", STM_EVAL_LEDOn, (void*) &led1, ENABLED);

    Task * task3 = new Task((char*) "LED2_OFF", STM_EVAL_LEDOff, (void*) &led2, DISABLED);
    Task * task4 = new Task((char*) "LED2_ON", STM_EVAL_LEDOn, (void*) &led2, ENABLED);

    Task * task5 = new Task((char*) "LED3_OFF", STM_EVAL_LEDOff, (void*) &led3, DISABLED);
    Task * task6 = new Task((char*) "LED3_ON", STM_EVAL_LEDOn, (void*) &led3, ENABLED);

    DelayBlock* delay1 = new DelayBlock(500);
    DelayBlock* delay2 = new DelayBlock(500);

    DelayBlock* delay3 = new DelayBlock(1000);
    DelayBlock* delay4 = new DelayBlock(1000);

    task1->setNexBlock(delay1);
    delay1->setNexBlock(task2);
    task2->setNexBlock(delay2);
    delay2->setNexBlock(task1);

    task3->setNexBlock(delay3);
    delay3->setNexBlock(task4);
    task4->setNexBlock(delay4);
    delay4->setNexBlock(task3);

//    ConditionBlock<volatile unsigned int>* condBlock1 = new ConditionBlock<volatile unsigned int>(cond1);
//    ConditionBlock<volatile unsigned int>* condBlock2 = new ConditionBlock<volatile unsigned int>(cond1);
//
//    ConditionBlock<volatile unsigned int>* condBlock3 = new ConditionBlock<volatile unsigned int>(cond3);
//    ConditionBlock<volatile unsigned int>* condBlock4 = new ConditionBlock<volatile unsigned int>(cond3);
//
//    condBlock1->setNextYesBlock(task1);
//    task1->setNexBlock(condBlock2);
//    condBlock2->setNextYesBlock(task2);
//    task2->setNexBlock(condBlock1);
//
//    condBlock3->setNextYesBlock(task3);
//    task3->setNexBlock(condBlock4);
//    condBlock4->setNextYesBlock(task4);
//    task4->setNexBlock(condBlock3);
//	Sensor *sensTest1 = new Sensor((char*)"Sens1");
//	Sensor *sensTest2 = new Sensor((char*)"Sens2");
//	Sensor *sensTest3 = new Sensor((char*)"Sens3");
//	Sensor *sensTest4 = new Sensor((char*)"Sens4");
//	ErrorCode (*funcx)(void *args);
//	funcx = (ErrorCode (*)(void *args))&Sensor::scan;
//	Task *task1 = new Task((char*)"LED1_OFF", STM_EVAL_LEDOff,(void*)&led1, cond1,ENABLED);
//	Task *task2 = new Task((char*)"LED1_ON",  STM_EVAL_LEDOn,(void*)&led1, cond1, DISABLED);
//
//	Task *task3 = new Task((char*)"LED2_OFF", STM_EVAL_LEDOff,(void*)&led2, cond2,ENABLED);
//	Task *task4 = new Task((char*)"LED2_ON", STM_EVAL_LEDOn,(void*)&led2, cond2, DISABLED);
//
//        Task *task5 = new Task((char*)"LED3_OFF", STM_EVAL_LEDOff,(void*)&led3, cond3,ENABLED);
//	Task *task6 = new Task((char*)"LED3_ON", STM_EVAL_LEDOn,(void*)&led3, cond3, DISABLED);
//
//
//        Task *task7 = new Task((char*)"LED4_OFF", STM_EVAL_LEDOff,(void*)&led4, cond4,ENABLED);
//	Task *task8 = new Task((char*)"LED4_ON", STM_EVAL_LEDOn,(void*)&led4, cond4, DISABLED);

    //Task *task1 = new Task((char*)"LED1_OFF", STM_EVAL_LEDOff,(void*)&led1, cond1,ENABLED);
    //      Task *task2 = new Task((char*)"LED1_ON",  STM_EVAL_LEDOn,(void*)&led1, cond1, DISABLED);
    //
    //      Task *task3 = new Task((char*)"LED2_OFF", STM_EVAL_LEDOff,(void*)&led2, cond2,ENABLED);
    //      Task *task4 = new Task((char*)"LED2_ON", STM_EVAL_LEDOn,(void*)&led2, cond2, DISABLED);
    //
    //        Task *task5 = new Task((char*)"LED3_OFF", STM_EVAL_LEDOff,(void*)&led3, cond3,ENABLED);
    //      Task *task6 = new Task((char*)"LED3_ON", STM_EVAL_LEDOn,(void*)&led3, cond3, DISABLED);
    //
    //
    //        Task *task7 = new Task((char*)"LED4_OFF", STM_EVAL_LEDOff,(void*)&led4, cond4,ENABLED);
    //      Task *task8 = new Task((char*)"LED4_ON", STM_EVAL_LEDOn,(void*)&led4, cond4, DISABLED);
//
//	task1->addNextYesTask(task2);
//	task2->addNextYesTask(task1);
//
//        task3->addNextYesTask(task4);
//	task4->addNextYesTask(task3);
//
//        task5->addNextYesTask(task6);
//	task6->addNextYesTask(task5);
//
//        task7->addNextYesTask(task8);
//	task8->addNextYesTask(task7);
    Scheduler::init();
    Scheduler::addThreadEntry (task1);
    Scheduler::addThreadEntry (task3);
  //  Scheduler::addThreadEntry (condBlock3);
    //Scheduler::addTask(task4,SYS_TICK);
    Scheduler::start();
    for (uint8_t i = 0; i < 15; i++)
      {
        a = 0;

        c = 0;
        d = 0;
        x = 0;
        //Scheduler::addTask(new Task((char*)"Task4", funcx,(void*)sensTest4, cond4, DISABLED),SYS_TICK);
      }

//  /* Test if Key push-button on STM320518-EVAL Board is pressed */
//  if (STM_EVAL_PBGetState(BUTTON_KEY) == 0x00)
//  { 
//    /* If Key is pressed, execute the IAP driver in order to re-program the Flash */
//    IAP_Init();
//    
//    /* Display main menu */
//    Main_Menu ();
//  }  
//  else
//  {/* Keep the user application running */
//
//    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
//    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
//    { 
//      /* Jump to user application */
//      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
//      Jump_To_Application = (pFunction) JumpAddress;
//      
//      /* Initialize user application's Stack Pointer */
//      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
//      
//      /* Jump to application */
//      Jump_To_Application();
//    }
//  }

    /* Infinite loop */
    while (1)
      {
      }
  }

/**
 * @brief  Initialize the IAP.
 * @param  None
 * @retval None
 */
void IAP_Init(void)
  {
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    /* Setup SysTick Timer for 1 msec interrupts.
     ------------------------------------------
     1. The SysTick_Config() function is a CMSIS function which configure:
     - The SysTick Reload register with value passed as function parameter.
     - Configure the SysTick IRQ priority to the lowest value (0x0F).
     - Reset the SysTick Counter register.
     - Configure the SysTick Counter clock source to be Core Clock Source (HCLK).
     - Enable the SysTick Interrupt.
     - Start the SysTick Counter.

     2. You can change the SysTick Clock source to be HCLK_Div8 by calling the
     SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8) just after the
     SysTick_Config() function call. The SysTick_CLKSourceConfig() is defined
     inside the stm32f0xx_misc.c file.

     3. You can change the SysTick IRQ priority by calling the
     NVIC_SetPriority(SysTick_IRQn,...) just after the SysTick_Config() function
     call. The NVIC_SetPriority() is defined inside the core_cm0.h file.

     4. To adjust the SysTick time base, use the following formula:

     Reload Value = SysTick Counter Clock (Hz) x  Desired Time base (s)

     - Reload Value is the parameter to be passed for SysTick_Config() function
     - Reload Value should not exceed 0xFFFFFF
     */
    if (SysTick_Config(SystemCoreClock / 1000))
      {
        /* Capture error */
        while (1)
          ;
      }
    /* Unlock the Flash Program Erase controller */
    // FLASH_If_Init();
    /* Enable the USART1 Interrupt */
    /* Enable and set Button EXTI Interrupt to the lowest priority */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x03;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/
    /* USART configured as follow:
     - BaudRate = 921600 baud
     - Word Length = 8 Bits
     - One Stop Bit
     - No parity
     - Hardware flow control disabled (RTS and CTS signals)
     - Receive and transmit enabled
     */
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    STM_EVAL_COMInit(COM1, &USART_InitStructure);
    /* Enable the USART Receive interrupt: this interrupt is generated when the
     USART1 receive data register is not empty */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

  }

#ifdef  USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t* file, uint32_t line)
  {
    /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
      {
      }
  }
#endif

/**
 * @}
 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
